//稀土掘金自动登录 实现自动发布文章流程
// @ts-check
import { test, expect } from "@playwright/test";
import fs from "fs";
import path from "path";

// 保存localStorage到本地文件
const LOCAL_STORAGE_FILE = path.join(
  __dirname,
  "..",
  "chaoxing-localstorage.json"
);
// 上次访问的页面
const LAST_URL_FILE = path.join(__dirname, "..", "chaoxing-last-url.txt");
// 保存cookie到本地文件
const COOKIES_FILE = path.join(__dirname, "..", "chaoxing-cookies.json");

test("稀土掘金自动登录 - 支持状态保存", async ({ page, context }) => {
  console.log("🚀 启动稀土掘金自动登录脚本...");

  // 尝试加载已保存的 localStorage
  let hasValidStorage = false;
  let lastVisitedUrl = "https://juejin.cn/";

  try {
    // 加载cookie到浏览器
    if (fs.existsSync(COOKIES_FILE)) {
      const cookiesData = JSON.parse(fs.readFileSync(COOKIES_FILE, "utf-8"));
      await context.addCookies(cookiesData);
    }
    // 检查 localStorage 文件是否存在
    if (fs.existsSync(LOCAL_STORAGE_FILE)) {
      const storageData = JSON.parse(
        fs.readFileSync(LOCAL_STORAGE_FILE, "utf-8")
      );

      // 先访问页面，然后设置 localStorage
      await page.goto("https://juejin.cn/");
      await page.evaluate((data) => {
        // 设置所有 localStorage 项
        Object.keys(data).forEach((key) => {
          localStorage.setItem(key, data[key]);
        });
      }, storageData);

      console.log("✅ 成功加载已保存的登录状态");
      hasValidStorage = true;

      // 加载上次访问的URL
      if (fs.existsSync(LAST_URL_FILE)) {
        lastVisitedUrl = fs.readFileSync(LAST_URL_FILE, "utf-8").trim();
        console.log(`📖 上次访问的页面: ${lastVisitedUrl}`);
      }
    } else {
      console.log("ℹ️  未找到保存的登录状态，将进行首次登录");
    }
  } catch (error) {
    console.log("⚠️  加载登录状态失败，将重新登录:", error.message);
    hasValidStorage = false;
  }

  // 如果有有效的 localStorage，直接跳转到上次访问的页面
  if (hasValidStorage) {
    console.log("🔄 尝试使用已保存的登录状态访问页面...");
    console.log(lastVisitedUrl);
    await page.goto(lastVisitedUrl); //跳转到上次访问的页面

    await page.waitForLoadState("networkidle"); //等待网络空闲

    // 验证登录状态是否仍然有效
    const currentUrl = page.url();
    console.log(`当前页面URL: ${currentUrl}`);

    console.log("🎉 登录状态有效，已成功访问页面！");
    console.log(`页面标题: ${await page.title()}`);

    // 自动发布文章功能
    console.log("📝 开始自动发布文章流程...");

    try {
      // 1. 点击创作者中心按钮
      console.log("🔍 查找创作者中心按钮...");

      await page.click('button:has-text("创作者中心")');
      console.log("✅ 成功点击创作者中心");

      // 等待页面加载
      await page.waitForLoadState("networkidle");

      // 2. 点击写文章按钮
      console.log("🔍 查找写文章按钮...");

      await page.getByRole("button", { name: "写文章" }).click();
      console.log("✅ 成功点击写文章按钮");

      // 等待新标签页打开
      const newPagePromise = context.waitForEvent("page");
      // 切换到新标签页
      console.log("✅ 成功切换到写文章页面");
      const newPage = await newPagePromise;
      await newPage.waitForLoadState("networkidle");

      // 3. 填写文章标题
      console.log("🔍 查找文章标题输入框...");

      // 等待页面完全加载
      await newPage.waitForLoadState("networkidle");

      // 尝试多种选择器策略
      let titleInput = null;
      try {
        // 首先尝试使用placeholder选择器
        titleInput = await newPage.waitForSelector(
          'input[placeholder="输入文章标题..."]',
          {
            timeout: 10000,
            state: "visible",
          }
        );
        console.log("✅ 使用placeholder选择器找到标题输入框");
      } catch (error) {
        console.log("❌ 所有选择器都失败了");
        throw new Error("无法找到标题输入框");
      }

      // 确保元素可见和可交互
      await titleInput.waitForElementState("stable");

      // 点击输入框以确保焦点
      await titleInput.click();

      // 清空现有内容并输入新标题
      await titleInput.fill("自动化发布文章");
      console.log("✅ 正在填写标题中........");

      // 等待一下确保输入完成
      await newPage.waitForTimeout(2000);

      // 验证标题是否填写成功
      const titleValue = await titleInput.inputValue();
      console.log(`✅ 标题填写成功: ${titleValue}`);

      // 4. 编写文章内容
      console.log("🔍 开始编写文章内容...");

      try {
        // 使用JavaScript直接操作CodeMirror编辑器
        await newPage.evaluate((title) => {
          // 查找CodeMirror编辑器
          const editor = document.querySelector(".CodeMirror");
          if (editor) {
            // 获取CodeMirror实例
            const cm = editor["CodeMirror"];
            if (cm) {
              // 设置文章内容
              const articleContent = `# ${title}

## 引言

本文介绍如何使用MCP (Model Context Protocol) 和 Playwright 来实现自动化文章内容编写功能。通过这种方式，我们可以实现智能化的内容创作流程。

## 技术背景

### MCP (Model Context Protocol)
MCP是一个用于连接AI模型与外部工具的协议，它允许AI模型与各种服务和API进行交互。

### Playwright
Playwright是一个强大的浏览器自动化工具，支持多种浏览器引擎，提供了丰富的API来进行网页操作。

## 实现步骤

### 1. 环境准备
- 安装Node.js和npm
- 安装Playwright
- 配置MCP服务器

### 2. 代码实现
\`\`\`javascript
// 示例代码
const { chromium } = require('playwright');

async function autoWriteArticle() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  // 导航到掘金编辑器
  await page.goto('https://juejin.cn/editor/drafts/new');
  
  // 填写标题
  await page.fill('input[placeholder="输入文章标题..."]', '测试标题');
  
  // 填写内容
  await page.fill('.CodeMirror textarea', '测试内容');
}
\`\`\`

### 3. 自动化流程
1. 自动登录掘金
2. 导航到编辑器页面
3. 填写文章标题
4. 编写文章内容
5. 自动保存或发布

## 优势

- **效率提升**: 自动化减少了重复性工作
- **一致性**: 确保内容格式的统一性
- **可扩展性**: 可以轻松添加新的功能模块
- **智能化**: 结合AI模型实现智能内容生成

## 注意事项

- 需要遵守网站的使用条款
- 确保内容的原创性和质量
- 合理控制自动化频率
- 注意账号安全

## 总结

通过MCP和Playwright的结合，我们可以构建一个强大的自动化内容创作系统。这不仅提高了工作效率，还为内容创作带来了新的可能性。

---

*本文为自动化测试内容，展示了技术实现的可行性。*`;

              cm.setValue(articleContent);
              return "内容已成功设置";
            }
          }
          return "未找到编辑器";
        }, titleValue);

        console.log("✅ 文章内容编写成功");

        // 验证内容是否编写成功
        const contentLength = await newPage.evaluate(() => {
          const editor = document.querySelector(".CodeMirror");
          if (editor && editor["CodeMirror"]) {
            const cm = editor["CodeMirror"];
            return cm.getValue().length;
          }
          return 0;
        });

        console.log(`✅ 文章内容长度: ${contentLength} 字符`);
        // await newPage.locator("button:has-text('发布')").click();
        await newPage.click('button:has-text("发布")');
        await newPage.waitForSelector(".panel", { timeout: 5000 });

        await newPage
          .locator('.category-list>> .item:has-text("前端")')
          .click();
        console.log("✅ 选择分类完成");
        await newPage
          .locator(".byte-select__wrap:has-text('请搜索添加标签')")
          .click();
        //点击byte-select-option 匹配前端点击
        await newPage.locator(".byte-select-option:has-text('前端')").click();
        console.log("✅ 点击标签完成");
        await newPage.locator(".summary-textarea textarea").click(); //获取文本框并点击
        await newPage
          .locator(".summary-textarea textarea")
          .fill(
            "这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。这是一个通过Playwright MCP自动化测试创建的编辑摘要内容。"
          ); //获取文本框填充内容
        await newPage.locator("button:has-text('确定并发布')").click();
        console.log("✅ 填充文本完成");
        console.log("✅ 文章发布成功！");
        await newPage.waitForTimeout(5000);
        // 等待一段时间查看结果
      } catch (error) {
        console.log("❌ 编写文章内容失败:", error.message);
        console.log("请手动完成文章内容编写");
      }
    } catch (error) {
      console.log("❌ 自动发布文章失败:", error.message);
      console.log("请手动完成文章发布流程");
    }

    return; // 登录状态有效，直接结束
  }

  // 如果没有有效存储或已过期，进行登录流程
  console.log("📝 开始手动登录流程...");

  // 确保在登录页面
  if (!page.url().includes("juejin.cn")) {
    await page.goto("https://juejin.cn/");
    await page.waitForLoadState("networkidle");
    console.log("页面已加载完成，现在查看页面元素...");
  }

  // 等待用户手动填写表单
  console.log("👤 请在浏览器中手动填写用户名和密码...");
  console.log("🔑 填写完成后，请手动点击登录按钮");
  console.log("⏳ 系统将自动检测登录状态变化并保存登录信息...");

  // 监听页面导航变化来检测登录
  let loginSuccess = false;
  let finalUrl = "";

  //监听网络请求变化
  page.on("response", async (response) => {
    // 监听登录相关的API响应
    if (
      response.url().includes("login") ||
      response.url().includes("passport")
    ) {
      const status = response.status();
      console.log(`🔍 检测到请求: ${response.url()}, 状态码: ${status}`);
    }
  });

  try {
    // 等待用户头像元素出现（登录成功的标志）
    await page.waitForSelector(".avatar"); // ✅ 推荐
    loginSuccess = true;
    finalUrl = page.url();
    console.log("🚩 成功获取登录成功标志");
  } catch (error) {
    console.log("⚠️ 等待登录成功超时，尝试其他检测方式...");
    return;
  }

  // 如果登录成功，保存 localStorage 和当前URL
  if (loginSuccess) {
    try {
      // 获取并保存 localStorage
      const localStorageData = await page.evaluate(() => {
        const data = {};
        for (let i = 0; i < localStorage.length; i++) {
          const key = localStorage.key(i);
          if (key) {
            data[key] = localStorage.getItem(key);
          }
        }
        return data;
      });
      //保存localStorage到本地文件
      fs.writeFileSync(
        LOCAL_STORAGE_FILE,
        JSON.stringify(localStorageData, null, 2)
      );
      //获取cookie所有的值，并保存到本地文件;
      const cookies = await context.cookies();
      fs.writeFileSync(COOKIES_FILE, JSON.stringify(cookies, null, 2));
      console.log("💾 Cookie与localStorage已保存到本地");

      // 保存当前URL
      fs.writeFileSync(LAST_URL_FILE, finalUrl);
      console.log(`📚 当前页面URL已保存: ${finalUrl}`);

      console.log("\n🔄 下次运行脚本时将自动使用已保存的登录状态");
    } catch (error) {
      console.log("⚠️  保存登录状态时出错:", error.message);
    }
  } else {
    console.log("❌ 登录流程未完成或失败");
    console.log("请重新运行脚本并确保正确填写登录信息");
  }
});
